/**
 * Copyright (c) 2009 Teoti Graphix, LLC See:
 *     http://tkarchitecture.teotigraphix.org
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 * 
 * @author Michael Schmalle mschmalle@teotigraphix.com
 */
package test.suite.dxframework.patterns.layer
{

import flash.events.IEventDispatcher;

import mx.core.IMXMLObject;

import org.flexunit.Assert;
import org.flexunit.async.Async;
import org.fluint.uiImpersonation.UIImpersonator;
import org.teotigraphix.dx.event.ComponentLayerEvent;
import org.teotigraphix.dx.interfaces.IActivate;
import org.teotigraphix.dx.interfaces.IComponentAware;
import org.teotigraphix.dx.interfaces.IComponentLayer;
import org.teotigraphix.dx.interfaces.IComponentLayerClient;

import test.suite.dxframework.support.component.TestComponent;
import test.suite.dxframework.support.event.TestComponentLayerEvent;
import test.suite.dxframework.support.layer.TestComponentLayer;
import test.suite.dxframework.support.layer.TestComponentLayerClient;
import test.suite.dxframework.support.layer.TestComponentLayerClient2;


public class TC_ComponentLayer
{
	//--------------------------------------------------------------------------
	//
	//  Private :: Variables
	//
	//--------------------------------------------------------------------------
	
	/**
	 * @private
	 */
	private var component:TestComponent;
	
	private var layer:TestComponentLayer;
	
	[Before(ui,async)]
	public function setUp():void
	{
		layer = new TestComponentLayer();
		component = new TestComponent();
		UIImpersonator.addChild(component);
	}
	
	[After]
	public function tearDown():void
	{
		layer = null;
		UIImpersonator.removeChild(component);
		component = null;
	}
	
	//--------------------------------------------------------------------------
	//
	//  Public Test :: Methods
	//
	//--------------------------------------------------------------------------
	
	[Test]
	/**
	 * Tests the <code>ToolKitLayer</code>'s implementations.
	 */
	public function test_ToolKitLayer_implements():void
	{
		Assert.assertTrue( "!IEventDispatcher", (layer is IEventDispatcher) );
		Assert.assertTrue( "!IMXMLObject", (layer is IMXMLObject) );
		Assert.assertTrue( "!IComponentLayer", (layer is IComponentLayer) );
		Assert.assertTrue( "!IComponentAware", (layer is IComponentAware) );
		Assert.assertTrue( "!IActivate", (layer is IActivate) );
	}
	
	[Test]
	/**
	 * Tests the <code>className</code>.
	 */
	public function test_get_className():void
	{
		Assert.assertEquals( "", "test.suite.dxframework.support.layer.TestComponentLayer", 
			layer.className );
	}
	
	[Test]	
	/**
	 * Tests the <code>component</code>.
	 */
	public function test_set_component():void
	{
		var tlayer:TestComponentLayer = new TestComponentLayer();
		tlayer.activate(component);
		
		// test that component is valid
		Assert.assertNotNull( "", tlayer.component );
		Assert.assertStrictlyEquals( "", component, tlayer.component );
		// test that commitComponent() ran
		Assert.assertTrue( "", tlayer.commitComponentFlag );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>activate()</code> method.
	 */
	public function test_call_activate_pre():void
	{
		var tlayer:TestComponentLayer = new TestComponentLayer();
		
		var o:Object = {};
		o.layer = tlayer
		o.component = component;
		
		// test that the layer dispatches LAYER_ACTIVATE
		Async.handleEvent( this, tlayer, ComponentLayerEvent.LAYER_ACTIVATE,
			layer_call_layerActivate_Handler, 500, o );
		// test that the component dispatches LAYER_ACTIVATE
		Async.handleEvent( this, component, ComponentLayerEvent.LAYER_ACTIVATE,
			component_call_layerActivate_Handler, 500, o );
		
		// call activate() pre register
		tlayer.activate(component);
		
		var client:TestComponentLayerClient = new TestComponentLayerClient();
		var client2:TestComponentLayerClient2 = new TestComponentLayerClient2();
		
		tlayer.registerClient( TestComponentLayerClient, client );
		tlayer.registerClient( TestComponentLayerClient2, client2 );
		
		Assert.assertTrue( "", tlayer.activateFlag );	
		
		// test that component gets set
		Assert.assertNotNull( "", tlayer.component );
		Assert.assertStrictlyEquals( "", component, tlayer.component );
		
		// test that a proxy get's it's activate() called
		Assert.assertTrue( "!client.isActive", client.isActive );
		Assert.assertTrue( "!client.activateFlag", client.activateFlag );
		
		Assert.assertTrue( "!client2.isActive", client2.isActive );
		Assert.assertTrue( "!client2.activateFlag", client2.activateFlag );
		
		// test the clients are in the collection
		var proxies:Array = tlayer.getClients();
		Assert.assertTrue( "proxies.length ! 2", (proxies.length == 2) );
		
		Assert.assertTrue( "", tlayer.hasClient( TestComponentLayerClient ) );
		Assert.assertTrue( "", tlayer.hasClient( TestComponentLayerClient2 ) );
		
		Assert.assertStrictlyEquals( "", client, tlayer.getClient( TestComponentLayerClient ) );
		Assert.assertStrictlyEquals( "", client2, tlayer.getClient( TestComponentLayerClient2 ) );
	}
	
	[Test]
	/**
	 * Tests the <code>activate()</code> method.
	 */
	public function test_call_activate_post():void
	{
		var tlayer:TestComponentLayer = new TestComponentLayer();
		
		var client:TestComponentLayerClient = new TestComponentLayerClient();
		var client2:TestComponentLayerClient2 = new TestComponentLayerClient2();
		
		tlayer.registerClient( TestComponentLayerClient, client );
		tlayer.registerClient( TestComponentLayerClient2, client2 );
		
		// call activate() post register
		tlayer.activate(component);
		
		Assert.assertTrue( "", tlayer.activateFlag );	
		
		// test that component gets set
		Assert.assertNotNull( "", tlayer.component );
		Assert.assertStrictlyEquals( "", component, tlayer.component );
		
		// test that a proxy get's it's activate() called
		Assert.assertTrue( "!client.activateFlag", client.activateFlag );
		Assert.assertTrue( "!client2.activateFlag", client2.activateFlag );
	}
	
	[Test]
	/**
	 * Tests the <code>activate()</code> method.
	 */
	public function test_call_activate_pre_post():void
	{
		var tlayer:TestComponentLayer = new TestComponentLayer();
		
		var client:TestComponentLayerClient = new TestComponentLayerClient();
		var client2:TestComponentLayerClient2 = new TestComponentLayerClient2();
		
		tlayer.registerClient( TestComponentLayerClient, client );
		
		// call activate() pre & post register
		tlayer.activate(component);
		
		tlayer.registerClient( TestComponentLayerClient2, client2 );
				
		Assert.assertTrue( "", tlayer.activateFlag );	
		
		// test that component gets set
		Assert.assertNotNull( "", tlayer.component );
		Assert.assertStrictlyEquals( "", component, tlayer.component );
		
		// test that a proxy get's it's activate() called
		Assert.assertTrue( "!client.activateFlag", client.activateFlag );
		Assert.assertTrue( "!client2.activateFlag", client2.activateFlag );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>deactivate()</code> method.
	 */
	public function test_call_deactivate():void
	{
		var tlayer:TestComponentLayer = new TestComponentLayer();
		
		var o:Object = {};
		o.layer = tlayer
		o.component = component;
		
		// test that the layer dispatches LAYER_DEACTIVATE
		Async.handleEvent( this, tlayer, ComponentLayerEvent.LAYER_DEACTIVATE,
			layer_call_layerDeactivate_Handler, 500, o );
		// test that the component dispatches LAYER_DEACTIVATE
		Async.handleEvent( this, component, ComponentLayerEvent.LAYER_DEACTIVATE,
			component_call_layerDeactivate_Handler, 500, o );		
		
		var client:TestComponentLayerClient = new TestComponentLayerClient();
		var client2:TestComponentLayerClient2 = new TestComponentLayerClient2();
		
		tlayer.registerClient( TestComponentLayerClient, client );
		tlayer.registerClient( TestComponentLayerClient2, client2 );
		
		tlayer.activate(component);
		
		tlayer.deactivate(component);
		
		Assert.assertTrue( "", tlayer.deactivateFlag );	
		
		// test that component gets set
		Assert.assertNull( "", tlayer.component );
		
		// test that a proxy get's it's activate() called
		Assert.assertTrue( "!client.activateFlag", client.deactivateFlag );
		Assert.assertTrue( "!client2.activateFlag", client2.deactivateFlag );
	}	
	
	[Test(async)]
	/**
	 * Tests the <code>createLayerEvent()</code> and 
	 * <code>dispatchAddEvent()</code> method.
	 */
	public function test_call_dispatchAddEvent():void
	{
		var tlayer:TestComponentLayer = new TestComponentLayer();
		
		var o:Object = {};
		o.layer = tlayer
		o.component = component;
		
		tlayer.activate(component);
		
		// test that the layer dispatches LAYER_DEACTIVATE
		Async.handleEvent( this, tlayer, TestComponentLayerEvent.CLIENT_ADD,
			layer_dispatchAddEvent_clientAdd_Handler, 500, o );
		// test that the component dispatches LAYER_DEACTIVATE
		Async.handleEvent( this, component, TestComponentLayerEvent.CLIENT_ADD,
			component_dispatchAddEvent_clientAdd_Handler, 500, o );	
		
		var client:TestComponentLayerClient = new TestComponentLayerClient();
		
		// test the registerClient() -> registerProxy()
		tlayer.registerClient( TestComponentLayerClient, client );
	}
	
	[Test(async)]
	/**
	 * Tests the <code>createLayerEvent()</code> and 
	 * <code>test_call_dispatchRemoveEvent()</code> method.
	 */
	public function test_call_dispatchRemoveEvent():void
	{
		var tlayer:TestComponentLayer = new TestComponentLayer();
		
		var o:Object = {};
		o.layer = tlayer
		o.component = component;
		
		tlayer.activate(component);
		
		// test that the layer dispatches TestClientLayerEvent.CLIENT_REMOVE
		Async.handleEvent( this, tlayer, TestComponentLayerEvent.CLIENT_REMOVE,
			layer_dispatchRemoveEvent_clientRemove_Handler, 500, o );
		// test that the component dispatches TestClientLayerEvent.CLIENT_REMOVE
		Async.handleEvent( this, component, TestComponentLayerEvent.CLIENT_REMOVE,
			component_dispatchRemoveEvent_clientRemove_Handler, 500, o );		
		
		var client:TestComponentLayerClient = new TestComponentLayerClient();
		
		// test the registerClient() -> registerProxy()
		tlayer.registerClient( TestComponentLayerClient, client );
		// test the removeClient() -> removeProxy()
		var c:IComponentLayerClient = tlayer.removeClient( TestComponentLayerClient );
		
		Assert.assertFalse( "", tlayer.hasClient( TestComponentLayerClient ) );
		Assert.assertStrictlyEquals( "", c, client );
	}
	
	//--------------------------------------------------------------------------
	//
	//  Protected :: Handlers
	//
	//--------------------------------------------------------------------------
	
	/**
	 * @private
	 */
	protected function layer_call_layerActivate_Handler( event:ComponentLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, ComponentLayerEvent.LAYER_ACTIVATE );
		Assert.assertEquals( "event.layer incorrect", event.layer, data.layer );
		Assert.assertEquals( "event.component incorrect", event.component, data.component );
		Assert.assertEquals( "event.currentTarget incorrect", event.currentTarget, data.layer);
	}
	
	/**
	 * @private
	 */
	protected function component_call_layerActivate_Handler( event:ComponentLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, ComponentLayerEvent.LAYER_ACTIVATE );
		Assert.assertEquals( "event.layer incorrect", event.layer, data.layer );
		Assert.assertEquals( "event.component incorrect", event.component, data.component );
		Assert.assertEquals( "event.currentTarget incorrect", event.currentTarget, data.component);
	}
	
	/**
	 * @private
	 */
	protected function layer_call_layerDeactivate_Handler( event:ComponentLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, ComponentLayerEvent.LAYER_DEACTIVATE );
		Assert.assertEquals( "event.layer incorrect", event.layer, data.layer );
		Assert.assertEquals( "event.component incorrect", event.component, data.component );
		Assert.assertEquals( "event.currentTarget incorrect", event.currentTarget, data.layer);
	}
	
	/**
	 * @private
	 */
	protected function component_call_layerDeactivate_Handler( event:ComponentLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, ComponentLayerEvent.LAYER_DEACTIVATE );
		Assert.assertEquals( "event.layer incorrect", event.layer, data.layer );
		Assert.assertEquals( "event.component incorrect", event.component, data.component );
		Assert.assertEquals( "event.currentTarget incorrect", event.currentTarget, data.component);
	}
	
	/**
	 * @private
	 */
	protected function layer_dispatchAddEvent_clientAdd_Handler( event:TestComponentLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, TestComponentLayerEvent.CLIENT_ADD );
	}
	
	/**
	 * @private
	 */
	protected function component_dispatchAddEvent_clientAdd_Handler( event:TestComponentLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, TestComponentLayerEvent.CLIENT_ADD );
	}
	
	/**
	 * @private
	 */
	protected function layer_dispatchRemoveEvent_clientRemove_Handler( event:TestComponentLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, TestComponentLayerEvent.CLIENT_REMOVE );
	}
	
	/**
	 * @private
	 */
	protected function  component_dispatchRemoveEvent_clientRemove_Handler( event:TestComponentLayerEvent, data:Object ):void 
	{
		Assert.assertEquals( "event.type incorrect", event.type, TestComponentLayerEvent.CLIENT_REMOVE );
	}	
}
}